home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-1.iso / Files / Tele / T / Terminal 1.7.sit / Terminal scripts / MiniBBS.s < prev    next >
Encoding:
Text File  |  1989-11-06  |  11.9 KB  |  462 lines  |  [TEXT/QED1]

  1. /*
  2.     Terminal 1.7
  3.     "MiniBBS.s"
  4.  
  5. This script sets up a small BBS. To try it out connect another computer
  6. directly to your Macintosh (an ImageWriter II cable can be used to connect
  7. two Macintosh computers) and set the variable "modem" to 0. In real
  8. operation you would set the variable "modem" to 1, configure your modem to
  9. auto-answer and wait for others to call you (set the dip switches on the
  10. modem so that a drop of the DTR line is recognized as a command to hang up).
  11.  
  12. When the BBS receives the string "RING\r" it waits for for ten seconds to
  13. receive the string "CONNECT 1200\r" (this indicates that the modem has
  14. answered an incoming call) and then it prompts for a password. Once the
  15. correct password is given the BSS will prompt for commands. The password is
  16. not echoed to the caller, nor is it echoed to the screen. The password to
  17. use is hard-coded into the script ("SECRET"). There is a retry limit of 3
  18. on the password, then the BBS will hang up.
  19.  
  20. The BBS is command line oriented. You enter commands on a line using a
  21. command name followed by a parameter if needed, then press "Return". The
  22. following commands are programmed in this mini BBS:
  23.  
  24.     Command            What it does
  25.  
  26.     ?                Display list of available commands
  27.     DIR                Folder catalog to see what files exist
  28.     DOWNLOAD name    Download a file from the BBS using X-Modem protocol
  29.     FILE name        Show file info (type, size, date)
  30.     INFO            Display information about this BBS
  31.     QUIT            Logout of the BBS
  32.     TIME            Display time statistics
  33.     TYPE name        Display a text file
  34.     UPLOAD name        Upload a file to the BBS using X-Modem protocol
  35.  
  36. There are some timeout values hard-coded into the script. If waiting for
  37. commands the BBS will timeout and log you out when no command is received
  38. after 3 minutes. There is also a login timeout of 30 minutes. If you have
  39. been logged in for 30 minutes you are logged out automatically.
  40.  
  41. The upload and download commands will not use MacBinary format. Any file
  42. uploaded is stored on the disk as received (it may be a file from another
  43. computer system, not necessarily a Macintosh). An upload cannot use the
  44. name of an existing file. There is no way to delete files. The folder on
  45. the disk where all file operations take place is the folder that can be set
  46. up using the "Binary file transfer" menu option. There is no way to switch
  47. to another folder thru BBS commands.
  48.  
  49. This script is a good example of the "Terminal" script language. It shows
  50. most constructs available in this subset of the C language. You should
  51. especially look for and understand the recognition of commands, where an
  52. array of function pointers is used, some pointer arithmetic is done, and
  53. functions are called indirectly thru pointers.
  54.  
  55. Note that the possibility to cancel scripts depends on the goodwill of the
  56. script itself. It should test the return codes of the intrinsic functions
  57. it calls and recognize the cancel return code (2) and then exit gracefully.
  58.  
  59. */
  60.  
  61. /* ----- Global data --------------------------------------------------- */
  62.  
  63. int modem = 1;                /* 0: direct connect, 1: auto-answer modem */
  64. int LIMIT0 = 60*60;            /* 60 seconds timeout for password */
  65. int LIMIT1 = 3*60*60;        /* 3 minutes timeout for command prompt */
  66. int LIMIT2 = 3600;            /* 30 minutes timeout for login */
  67. char PASSWORD[] = "SECRET";    /* Login password */
  68.  
  69. int TIMEOUT = 1;
  70. int CANCEL = 2;        /* Script canceled by menu command */
  71. int ABORT = 3;        /* Abort by (2 consecutive) control-X characters */
  72. int ILLEGAL = 4;    /* Wrong password */
  73. int QUIT = 5;
  74.  
  75. char M_timeout[]    = "\r*** Timeout\r";
  76. char M_error[]        = "*** Error\r";
  77. char M_prompt[]        = "\r> ";
  78. char M_fileErr[]     = "\r*** File error %i\r";
  79. char M_catalog[]    = "TYPE D-FORK R-FORK   CREATED    MODIFIED   NAME\r";
  80. char M_file[]        = "%s %6i %6i %s %s %s\r";
  81. char M_abort[]        = "Press control-X twice to abort\r";
  82.  
  83. char *Days[] = {            /* Weekday names */
  84.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  85. };
  86.  
  87. char *Month[] = {            /* Month names */
  88.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  89.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  90. };
  91.  
  92. int IGNORE = -1;
  93.  
  94. char Line[256];                /* Command line */
  95. char *Mark;                    /* Running pointer into command line */
  96. int Timer;                    /* Login timer */
  97.  
  98. /* ----- Convert date and time to string ------------------------------- */
  99.  
  100. sec2str (int sec, char *s)
  101. {
  102.     int year, month, day, hour, minute, second, weekday;
  103.  
  104.     date(sec, &year, &month, &day, &hour, &minute, &second, &weekday);
  105.     format(s, "%02i-%s-%04i %02i:%02i:%02i %s",
  106.         day, Month[month-1], year, hour, minute, second, Days[weekday-1]);
  107. }
  108.  
  109. /* ----- Type date and time -------------------------------------------- */
  110.  
  111. clock (int sec)
  112. {
  113.     char s[256];
  114.  
  115.     sec2str(sec, s);
  116.     type("%s\r", s);
  117. }
  118.  
  119. /* ----- Main function ------------------------------------------------- */
  120.  
  121. main ()
  122. {
  123.     int flg = 0, e = 0, i;
  124.  
  125.     display("MiniBBS activated (%i bytes free)\r", stack());
  126.     setup(
  127.         2,        /* 1200 baud */
  128.         1,        /* 8 data */
  129.         0,        /* no parity */
  130.         0,        /* 1 stop */
  131.         IGNORE,    /* port: no change */
  132.         IGNORE);/* DTR: no change */
  133.     terminal(
  134.         0,        /* Local echo off */
  135.         0,        /* Remote echo off */
  136.         0,        /* AutoLF off */
  137.         1);        /* Save & display on */
  138.     while (!e && flg != CANCEL) {
  139.         lecho(0);    /* Local echo off */
  140.         recho(0);    /* Remote echo off */
  141.         if (modem) {
  142.             setdtr(0);    /* Negate DTR: modem hangs up */
  143.             pause(60);
  144.             setdtr(1);    /* Assert DTR: now back in command mode */
  145.             for (i = 0; i < 5; ++i) {
  146.                 type("ATZ\r");                            /* Reset modem */
  147.                 if (!(e = prompt("OK\r", 120))) {
  148.                     pause(30);
  149.                     /* Modem setup */
  150.                     type("ATE0X1S2=255S9=4S0=2S7=60S10=14S9=12\r");
  151.                     if (!(e = prompt("OK\r", 120))) {
  152.                         lecho(1);                        /* Local echo on */
  153.                         break;
  154.                     }
  155.                 }
  156.             }
  157.             if (e)
  158.                 break;    /* Could not setup modem */
  159.             if (!(flg = prompt("RING\r", 0)))
  160.                 if (!(flg = prompt("CONNECT 1200\r", 600))) {
  161.                     pause(300);                    /* Give modem a chance */
  162.                     flg = loop();
  163.                 }
  164.         } else {        /* Direct connection */
  165.             if (!(flg = prompt("\r", 0)))
  166.                 flg = loop();
  167.         }
  168.     }
  169.     if (modem) {
  170.         setdtr(0);    /* Negate DTR: modem hangs up */
  171.         pause(60);
  172.     }
  173.     setdtr(1);    /* Assert DTR: now back in command mode */
  174.     terminal(
  175.         0,        /* Local echo off */
  176.         0,        /* Remote echo off */
  177.         0,        /* AutoLF off */
  178.         1);        /* Save & display on */
  179.     if (e == TIMEOUT)
  180.         display("Modem problem\r");
  181.     display("End of MiniBBS mode\r");
  182. }
  183.  
  184. /* ----- Login session ------------------------------------------------- */
  185.  
  186. loop ()
  187. {
  188.     int flg, retry;
  189.  
  190.     /* Prompt for password (3 retries), wait for it, check it */
  191.  
  192.     retry = 3;
  193.     while(retry--) {
  194.         type("\rPassword: ");
  195.         save(0);                            /* Save & display off */
  196.         flg = nextline(Line, LIMIT0);
  197.         save(1);                            /* Save & display on */
  198.         if (flg == CANCEL)
  199.             return flg;
  200.         if (flg == TIMEOUT)
  201.             type(M_timeout);
  202.         if (flg == 0) {
  203.             if (!strcmp(Line, PASSWORD))
  204.                 break;                        /* Correct password */
  205.             flg = ILLEGAL;                    /* Wrong password */
  206.         }
  207.     }
  208.     if (flg) {
  209.         type("\rBye bye...\r");
  210.         return flg;                            /* Wrong password */
  211.     }
  212.  
  213.     /* Password was correct, now logged in */
  214.  
  215.     type("\rWellcome to MiniBBS\r");        /* Type date & time and ... */
  216.     clock(Timer = time());                    /*     start login timer */
  217.     recho(1);                                /* Remote echo on */
  218.  
  219.     /* Prompt and wait for commands (with timeout) */
  220.  
  221.     flg = 0;
  222.     while (!flg) {
  223.         type(M_prompt);
  224.         if ((flg = nextline(Line, LIMIT1)) == CANCEL)
  225.             return flg;                        /* Cancel */
  226.         if (!flg) {
  227.             flg = command();                /* Execute command */
  228.             if ((time() - Timer) > LIMIT2)
  229.                 flg = TIMEOUT;                /* Set timeout */
  230.         }
  231.     }
  232.  
  233.     /* Log out (command has set "flg" to non-zero value) */
  234.  
  235.     recho(0);                        /* Remote echo off */
  236.     if (flg == TIMEOUT)
  237.         type(M_timeout);
  238.     type("\rThank you for using MiniBBS\r");
  239.     datetime();
  240.     return flg;                        /* Timeout, cancel or quit */
  241. }
  242.  
  243. /* ----- Execute command line ------------------------------------------ */
  244.  
  245. command ()
  246. {
  247.     char name[256];            /* Command name extracted from command line */
  248.     char **p = Commands;    /* Pointer into command names array */
  249.  
  250.     Mark = Line;            /* Reset command line pointer */
  251.     if (getnext(name)) {    /* Get first word from command line */
  252.         while (*p) {        /* Search thru valid command names */
  253.             if (!strcmp(name, *p))
  254.                 return (Pointers[p - Commands])();    /* Execute command */
  255.             ++p;
  256.         }
  257.     }
  258.     type(M_error);            /* Command not recognized */
  259.     return 0;
  260. }
  261.  
  262. /* ----- Get next word from command line ------------------------------- */
  263.  
  264. getnext (char *s)
  265. {
  266.     int n;
  267.  
  268.     n = 0;
  269.     while (*Mark == ' ' && n < 255) {    /* Skip leading spaces */
  270.         ++Mark;
  271.         ++n;
  272.     }
  273.     n = 0;
  274.     while (*Mark && *Mark != ' ' && n < 255) {    /* Copy word */
  275.         *s++ = *Mark++;
  276.         ++n;
  277.     }
  278.     *s = '\0';        /* \0 as end of string */
  279.     if (*Mark)
  280.         ++Mark;        /* Skip blank, now Mark -> name */
  281.     return n;        /* Return string length */
  282. }
  283.  
  284. /* ----- Help command -------------------------------------------------- */
  285.  
  286. help ()
  287. {
  288.     char **p = Helps, **q = Commands;
  289.  
  290.     while (*p && *q)
  291.         type("%-10s - %s\r", *q++, *p++);
  292.     return 0;        /* Don't quit */
  293. }
  294.  
  295. /* ----- Info command -------------------------------------------------- */
  296.  
  297. info ()
  298. {
  299.     int flg = 0, n = 0;
  300.  
  301.     while (!flg)
  302.         flg = type("%4i. Press ctrl-X twice to cancel\r", n++);
  303.     return 0;        /* Dont't quit */
  304. }
  305.  
  306. /* ----- Quit command -------------------------------------------------- */
  307.  
  308. quit ()
  309. {
  310.     return QUIT;    /* Now quit */
  311. }
  312.  
  313. /* ----- Type date & time and login time ------------------------------- */
  314.  
  315. datetime ()
  316. {
  317.     clock(time());
  318.     type("Login time = %i seconds\r", time() - Timer);
  319.     return 0;        /* Don't quit */
  320. }
  321.  
  322. /* ----- Type file directory ------------------------------------------- */
  323.  
  324. directory ()
  325. {
  326.     int i;
  327.     char name[32];
  328.     char ftype[5];
  329.     int data, rsrc, creat, modif;
  330.     char cd[32], md[32];
  331.  
  332.     type(M_catalog);
  333.     for (i = 1; ; ++i) {
  334.         if (catalog(i, name, ftype, &data, &rsrc, &creat, &modif))
  335.             break;
  336.         sec2str(creat, cd);
  337.         sec2str(modif, md);
  338.         ftype[4] = cd[11] = md[11] = '\0';    /* Truncate strings */
  339.         if (type(M_file, ftype, data, rsrc, cd, md, name)) {
  340.             ++i;
  341.             break;
  342.         }
  343.     }
  344.     type("%i files listed\r", i - 1);
  345.     return 0;        /* Don't quit */
  346. }
  347.  
  348. /* ----- Type file info ------------------------------------------------ */
  349.  
  350. fileinfo ()
  351. {
  352.     int err;
  353.     char ftype[5];
  354.     int data, rsrc, creat, modif;
  355.     char cd[32], md[32];
  356.  
  357.     if (err = catalog(0, Mark, ftype, &data, &rsrc, &creat, &modif))
  358.         type(M_fileErr, err);
  359.     else {
  360.         type(M_catalog);
  361.         sec2str(creat, cd);
  362.         sec2str(modif, md);
  363.         ftype[4] = cd[11] = md[11] = '\0';    /* Truncate strings */
  364.         type(M_file, ftype, data, rsrc, cd, md, Mark);
  365.     }
  366.     return 0;        /* Don't quit */
  367. }
  368.  
  369. /* ----- Type TEXT file ------------------------------------------------ */
  370.  
  371. typefile ()
  372. {
  373.     int err;
  374.  
  375.     type(M_abort);
  376.     if (err = send(Mark))
  377.         type(M_fileErr, err);
  378.     return 0;        /* Don't quit */
  379. }
  380.  
  381. /* ----- Download file (X-Modem) --------------------------------------- */
  382.  
  383. downloadfile ()
  384. {
  385.     int err;
  386.     int ftype, data, rsrc, creat, modif;
  387.  
  388.     if (!(err = catalog(0, Mark, &ftype, &data, &rsrc, &creat, &modif))) {
  389.         type("Please start download. %s", M_abort);
  390.         err = upload(Mark, 0);
  391.     }
  392.     if (err)
  393.         type(M_fileErr, err);
  394.     return 0;        /* Don't quit */
  395. }
  396.  
  397. /* ----- Upload file (X-Modem) ----------------------------------------- */
  398.  
  399. uploadfile ()
  400. {
  401.     int err;
  402.     int ftype, data, rsrc, creat, modif;
  403.  
  404.     if (!(err = catalog(0, Mark, &ftype, &data, &rsrc, &creat, &modif)))
  405.         type("*** File <%s> already exists\r", Mark);
  406.     else {
  407.         type("Please start upload. %s", M_abort);
  408.         if (err = download(Mark, 0))
  409.             type(M_fileErr, err);
  410.     }
  411.     return 0;        /* Don't quit */
  412. }
  413.  
  414. /* ----- Not yet available command ------------------------------------- */
  415.  
  416. notyet ()
  417. {
  418.     type("Not yet available\r");
  419.     return 0;        /* Don't quit */
  420. }
  421.  
  422. /* ----- Command info -------------------------------------------------- */
  423.  
  424. char *Commands[] = {        /* Command keywords */
  425.     "?",
  426.     "DIR",
  427.     "DOWNLOAD",
  428.     "FILE",
  429.     "INFO",
  430.     "QUIT",
  431.     "TIME",
  432.     "TYPE",
  433.     "UPLOAD",
  434.     0
  435. };
  436.  
  437. char *Helps[] = {            /* Help text for each command */
  438.     "Display this help text",
  439.     "Directory of files",
  440.     "<name> Download file",
  441.     "<name> File info",
  442.     "Display system information",
  443.     "Logout of the system",
  444.     "Show date and time",
  445.     "<name> Type text file",
  446.     "<name> Upload file",
  447.     0
  448. };
  449.  
  450. int Pointers[] = {            /* Pointers to command functions */
  451.     help,
  452.     directory,
  453.     downloadfile,
  454.     fileinfo,
  455.     info,
  456.     quit,
  457.     datetime,
  458.     typefile,
  459.     uploadfile,
  460.     0
  461. };
  462.